#include <string.h>
#include <stdint.h>

#include "check.h"
#include "common_interface.h"
#include "check_interface.h"
#include "common_errno.h"

START_TEST(test_1_ok) {
    uint8_t number = 0x0f - 1;
    common_byte_type type = COMMON_BYTE_ONE;
    int i = 0;

    ck_assert_int_eq(common_byte_1_set(&number, COMMON_BYTE_ONE, 0), COM_OK);
    ck_assert_int_eq(number, 0x0f);

    // 低四位判断
    for(i = 0; i < 4; i++) {
        ck_assert_int_eq(common_byte_1_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ONE);
    }

    // 高四位判断
    for(i = 4; i < 8; i++) {
        ck_assert_int_eq(common_byte_1_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ZERO);
    }
}
END_TEST;

START_TEST(test_1_input) {
    uint8_t number = 0x0f - 1;
    common_byte_type type = COMMON_BYTE_ONE;

    ck_assert_int_eq(common_byte_1_set(NULL, COMMON_BYTE_ONE, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_1_set(&number, 2, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_1_set(&number, -1, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_1_set(&number, COMMON_BYTE_ONE, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_1_set(&number, COMMON_BYTE_ONE, 8), COM_BAD_INPUT);

    ck_assert_int_eq(common_byte_1_get(NULL, &type, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_1_get(&number, NULL, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_1_get(&number, &type, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_1_get(&number, &type, 8), COM_BAD_INPUT);
}
END_TEST;

START_TEST(test_2_ok) {
    uint16_t number = 0x00ff - 1;
    common_byte_type type = COMMON_BYTE_ONE;
    int i = 0;

    ck_assert_int_eq(common_byte_2_set(&number, COMMON_BYTE_ONE, 0), COM_OK);
    ck_assert_int_eq(number, 0x00ff);

    for(i = 0; i < 8; i++) {
        ck_assert_int_eq(common_byte_2_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ONE);
    }

    for(i = 8; i < 16; i++) {
        ck_assert_int_eq(common_byte_2_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ZERO);
    }
}
END_TEST;

START_TEST(test_2_input) {
    uint16_t number = 0x00ff - 1;
    common_byte_type type = COMMON_BYTE_ONE;

    ck_assert_int_eq(common_byte_2_set(NULL, COMMON_BYTE_ONE, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_2_set(&number, 2, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_2_set(&number, -1, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_2_set(&number, COMMON_BYTE_ONE, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_2_set(&number, COMMON_BYTE_ONE, 16), COM_BAD_INPUT);

    ck_assert_int_eq(common_byte_2_get(NULL, &type, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_2_get(&number, NULL, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_2_get(&number, &type, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_2_get(&number, &type, 16), COM_BAD_INPUT);
}
END_TEST;

START_TEST(test_4_ok) {
    uint32_t number = 0x0000ffff - 1;
    common_byte_type type = COMMON_BYTE_ONE;
    int i = 0;

    ck_assert_int_eq(common_byte_4_set(&number, COMMON_BYTE_ONE, 0), COM_OK);
    ck_assert_int_eq(number, 0x0000ffff);

    for(i = 0; i < 16; i++) {
        ck_assert_int_eq(common_byte_4_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ONE);
    }

    for(i = 16; i < 32; i++) {
        ck_assert_int_eq(common_byte_4_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ZERO);
    }
}
END_TEST;

START_TEST(test_4_input) {
    uint32_t number = 0x0000ffff - 1;
    common_byte_type type = COMMON_BYTE_ONE;

    ck_assert_int_eq(common_byte_4_set(NULL, COMMON_BYTE_ONE, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_4_set(&number, 2, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_4_set(&number, -1, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_4_set(&number, COMMON_BYTE_ONE, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_4_set(&number, COMMON_BYTE_ONE, 32), COM_BAD_INPUT);

    ck_assert_int_eq(common_byte_4_get(NULL, &type, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_4_get(&number, NULL, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_4_get(&number, &type, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_4_get(&number, &type, 32), COM_BAD_INPUT);
}
END_TEST;

START_TEST(test_8_ok) {
    uint64_t number = 0x00000000ffffffff - 1;
    common_byte_type type = COMMON_BYTE_ONE;
    int i = 0;

    ck_assert_int_eq(common_byte_8_set(&number, COMMON_BYTE_ONE, 0), COM_OK);
    ck_assert_int_eq(number, 0x00000000ffffffff);

    for(i = 0; i < 32; i++) {
        ck_assert_int_eq(common_byte_8_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ONE);
    }

    for(i = 50; i < 64; i++) {
        ck_assert_int_eq(common_byte_8_get(&number, &type, i), COM_OK);
        ck_assert_int_eq(type, COMMON_BYTE_ZERO);
    }
}
END_TEST;

START_TEST(test_8_input) {
    uint64_t number = 0x00000000ffffffff - 1;
    common_byte_type type = COMMON_BYTE_ONE;
    
    ck_assert_int_eq(common_byte_8_set(NULL, COMMON_BYTE_ONE, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_8_set(&number, 2, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_8_set(&number, -1, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_8_set(&number, COMMON_BYTE_ONE, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_8_set(&number, COMMON_BYTE_ONE, 64), COM_BAD_INPUT);

    ck_assert_int_eq(common_byte_8_get(NULL, &type, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_8_get(&number, NULL, 0), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_8_get(&number, &type, -1), COM_BAD_INPUT);
    ck_assert_int_eq(common_byte_8_get(&number, &type, 64), COM_BAD_INPUT);
}
END_TEST;

Suite *check_byte(void)
{
    Suite *s;
    TCase *tc_core;

    s = suite_create("byte get & set test");

    tc_core = tcase_create("core");
    tcase_add_test(tc_core, test_1_ok);
    tcase_add_test(tc_core, test_1_input);
    tcase_add_test(tc_core, test_2_ok);
    tcase_add_test(tc_core, test_2_input);
    tcase_add_test(tc_core, test_4_ok);
    tcase_add_test(tc_core, test_4_input);
    tcase_add_test(tc_core, test_8_ok);
    tcase_add_test(tc_core, test_8_input);

    suite_add_tcase(s, tc_core);

    return s;
}